/**
 * 素材管理相关
 * @authors 杨兴洲（of2502）
 * @date    2017/2/28 17:54
 * @version 1.0
 */

import { Router } from 'express';
import * as fs from 'fs';
import { get } from 'request';
import * as cheerio from 'cheerio';
import UserService from '../../service/user-service';
import WeixinMaterialService from '../../service/weixin-material-service';
import upload from '../../util/mediaUpload-util';
import CONFIG from '../../config';
import MediaService from '../../service/media-service';
import * as Busboy from 'busboy';
import { getOssClient } from '@qianmi/x-site-common/util/oss';
const ossClient = getOssClient(CONFIG.OSS_CONFIG);

const router = Router();

/**
 * 获取素材列表
 * /weixin/material/list/:type?page&pageSize
 */
router.get('/list/:type', (req, res, next) => {
  (async () => {
    try {
      const type = req.params.type;
      const page = req.query.page || 1;
      const pageSize = req.query.pageSize || 20;

      // 验证条件
      // 1. type
      // 2. page & pageSize > 0
      if (!['image', 'video', 'voice', 'news'].includes(type)) {
        let error = new Error();
        error['errcode'] = 10001;
        error['errmsg'] = '素材类型参数错误';
        return next(error);
      }

      if (pageSize > 20) {
        let error = new Error();
        error['errcode'] = 10002;
        error['errmsg'] = '分页超过最大值';
        return next(error);
      }

      const { userID } = res.locals;
      const access_token = await UserService.getAccessToken(userID);
      const result = await WeixinMaterialService.getList({
        access_token,
        type,
        offset: (page - 1) * pageSize,
        count: pageSize
      });
      res.status(200).json(result);
    } catch (error) {
      next(error);
    }
  })();
});

router.get('/count', (req, res, next) => {
  (async () => {
    try {
      const { userID } = res.locals;
      const access_token = await UserService.getAccessToken(userID);
      const result = await WeixinMaterialService.getCount(access_token);
      res.status(200).json(result);
    } catch (error) {
      next(error);
    }
  })();
});

/**
 * 上传素材
 * 图片（image）、语音（voice）、视频（video）和缩略图（thumb）
 */
/**
 * 素材校验
 */

function checkMaterial(fileSize, fileExt, body) {
  let type = body.type;
  if (['image', 'video', 'voice', 'thumb', 'article_img'].indexOf(type) === -1) {
    let error = new Error();
    error['errcode'] = 10001;
    error['errmsg'] = '素材类型错误';
    throw error;
  }

  if (type === 'image') {
    if (fileSize > 2 * 1024 * 1024) {
      let error = new Error();
      error['errcode'] = 10002;
      error['errmsg'] = '图片大小超过2M';
      throw error;
    }

    if (!/bmp|jpeg|jpg|png|gif$/.test(fileExt)) {
      let error = new Error();
      error['errcode'] = 10002;
      error['errmsg'] = '图片格式不支持' + fileExt;
      throw error;
    }
  }

  if (type === 'voice') {
    if (fileSize > 2 * 1024 * 1024) {
      let error = new Error();
      error['errcode'] = 10002;
      error['errmsg'] = '音频大小超过2M';
      throw error;
    }
    if (!/mp3|wma|wav|amr$/.test(fileExt)) {
      let error = new Error();
      error['errcode'] = 10002;
      error['errmsg'] = '音频格式不支持' + fileExt;
      throw error;
    }
  }

  if (type === 'thumb') {
    if (fileSize > 64 * 1024) {
      let error = new Error();
      error['errcode'] = 10002;
      error['errmsg'] = '缩略图大小超过64KB';
      throw error;
    }
    if (!/jpg/.test(fileExt)) {
      let error = new Error();
      error['errcode'] = 10002;
      error['errmsg'] = '缩略图格式只支持JPG';
      throw error;
    }
  }

  if (type === 'video') {
    let { title, introduction } = body;
    if (fileSize > 10 * 1024 * 1024) {
      let error = new Error();
      error['errcode'] = 10002;
      error['errmsg'] = '视频大小超过10M';
      throw error;
    }
    if (!title || !introduction) {
      let error = new Error();
      error['errcode'] = 10002;
      error['errmsg'] = '缺少参数title或introduction';
      throw error;
    }

    if (!/mp4/.test(fileExt)) {
      let error = new Error();
      error['errcode'] = 10002;
      error['errmsg'] = '视频格式只支持MP4';
      throw error;
    }
  }
  //文章内图片
  if (type === 'article_img') {
    if (fileSize > 1024 * 1024) {
      let error = new Error();
      error['errcode'] = 10002;
      error['errmsg'] = '文章内图片大小超过1M';
      throw error;
    }

    if (!/jpg|jpeg|png/.test(fileExt)) {
      let error = new Error();
      error['errcode'] = 10002;
      error['errmsg'] = '文章内图片只支持jpg';
      throw error;
    }
  }
  return true;
}

router.post('/upload', (req, res, next) => {
  (async () => {
    try {
      let contentLength = req.headers['content-length'] || 0;
      const { userID } = res.locals;
      const { authorizer_appid: appID } = await UserService.getInfo(userID);
      const access_token = await UserService.getAccessToken(userID);
      let busboy = new Busboy({ headers: req.headers });
      busboy.on('file', function(fieldName, media, filename) {
        (async () => {
          try {
            let ext = filename.split('.')[1];
            checkMaterial(contentLength, ext, req.body);
            let { type, title, introduction } = req.body;
            let remotePath = `x-weixin/${userID}/images/${filename.replace(`.${ext}`, `-${Date.now()}.${ext}`)}`;
            let data = await ossClient.putObjectAbsolute(media, remotePath);
            let aliUrl = data.url;
            const result = type === 'article_img'
              ? await WeixinMaterialService.addArticleImg({ access_token, media: get(aliUrl) })
              : await WeixinMaterialService.addItem({ access_token, type, media: get(aliUrl), title, introduction });
            res.status(200).json(Object.assign(result, { aliUrl }));
            const { media_id, url } = result;
            if (media_id) {
              await MediaService.createMedia({ appID, media_id, url, aliUrl, type });
            }
          } catch (e) {
            media.resume();
            req.unpipe(busboy);
            busboy.removeAllListeners();
            next(e);
          }
        })();
      });
      busboy.on('field', function(fieldName, val) {
        let tem = {};
        tem[fieldName] = val;
        Object.assign(req.body, tem);
      });
      busboy.on('finish', function() {
        req.unpipe(busboy);
        busboy.removeAllListeners();
      });
      req.pipe(busboy);
    } catch (e) {
      next(e);
    }
  })();
});

/**
 * 上传素材通过远程路径
 */
router.post('/upload/v2', (req, res, next) => {
  // request
  (async () => {
    try {
      const { type, title, introduction, media_path } = req.body;
      const { userID } = res.locals;
      const { authorizer_appid: appID } = await UserService.getInfo(userID);
      const access_token = await UserService.getAccessToken(userID);
      const result = type === 'article_img'
        ? await WeixinMaterialService.addArticleImg({ access_token, media: get(media_path) })
        : await WeixinMaterialService.addItem({ access_token, type, media: get(media_path), title, introduction });
      res.status(200).json(result);
      const { media_id, url } = result;
      if (media_id) {
        await MediaService.createMedia({ appID, media_id, url, type });
      }
    } catch (error) {
      next(error);
    }
  })();
});

/**
 * 图文素材 校验
 * @param req
 * @param res
 * @param next
 */
function checkContent(req, res, next) {
  (async () => {
    let { articles } = req.body;
    // 数据校验
    let isArray = true;
    if (!Array.isArray(articles)) {
      articles = [articles];
      isArray = false;
    }
    const { userID } = res.locals;
    const access_token = await UserService.getAccessToken(userID);

    //收集非微信图片
    let imgList = articles.reduce((result, current) => {
      let { content = '' } = current;
      let $ = cheerio.load(content);
      $('img').each(function(index, element) {
        let src = element.attribs.src;
        if (src && !src.startsWith('http://mmbiz.qpic.cn') && !result.includes(src)) {
          result.push(src);
        }
      });
      return result;
    }, []);
    //非微信图片上传微信 并且将content中的图片链接替换为上传后的图片(字符串处理)
    articles = JSON.stringify(articles);
    for (let i = 0, len = imgList.length; i < len; i++) {
      let fromSrc = imgList[i];
      let toSrc = '';
      try {
        let result = await WeixinMaterialService.addArticleImg({ access_token, media: get(fromSrc) });
        toSrc = result.url;
      } catch (e) {
        console.error(e);
        toSrc = fromSrc;
      }
      //将content中的图片链接替换为上传后的图片
      let reg = new RegExp(fromSrc, 'g');
      articles = articles.replace(reg, toSrc);
    }
    req.body.articles = !isArray ? JSON.parse(articles)[0] : JSON.parse(articles);
    next();
  })();
}

/**
 * 上传图文素材 中间件处理图文中的 图片 上传微信
 */
router.post('/upload/article', checkContent, (req, res, next) => {
  (async () => {
    try {
      const { articles } = req.body;
      // 数据校验
      if (!Array.isArray(articles)) {
        const error = new Error();
        error['errcode'] = 10002;
        error['errmsg'] = 'articles格式错误';
        return next(error);
      }

      const { userID } = res.locals;
      const access_token = await UserService.getAccessToken(userID);
      const result = await WeixinMaterialService.addArticle({ access_token, articles });
      res.status(200).json(result);
    } catch (error) {
      next(error);
    }
  })();
});

/**
 * 获取media信息
 */
router.get('/detail', (req, res, next) => {
  (async () => {
    try {
      let { media_id, type = 'image' } = req.query;

      // 数据校验
      if (!media_id) {
        const error = new Error();
        error['errcode'] = 10001;
        error['errmsg'] = '缺少参数media_id';
        return next(error);
      }

      const { userID } = res.locals;
      const access_token = await UserService.getAccessToken(userID);
      if (type === 'mpnews') {
        const result = await WeixinMaterialService.getItem({ access_token, media_id });
        return res.status(200).json(result);
      }
      if (type === 'voice' || type === 'video') {
        const error = new Error();
        error['errcode'] = 20001;
        error['errmsg'] = '暂不支持获取voice/video预览信息';
        return next(error);
      }
      const result = await MediaService.getDetail(media_id);
      res.status(200).json(result);
    } catch (error) {
      next(error);
    }
  })();
});

router.get('/download', (req, res, next) => {
  (async () => {
    try {
      const { media_id } = req.params;

      // 数据校验
      if (!media_id) {
        const error = new Error();
        error['errcode'] = 10001;
        error['errmsg'] = '缺少参数media_id';
        return next(error);
      }

      const { userID } = res.locals;
      const access_token = await UserService.getAccessToken(userID);
      const result = await WeixinMaterialService.getItem({ access_token, media_id });
      res.status(200).json(result);
    } catch (error) {
      next(error);
    }
  })();
});

/**
 * 获取素材详情
 * 视频/图文
 */
router.get('/:media_id', (req, res, next) => {
  (async () => {
    try {
      const { media_id } = req.params;

      // 数据校验
      if (!media_id) {
        const error = new Error();
        error['errcode'] = 10001;
        error['errmsg'] = '缺少参数media_id';
        return next(error);
      }

      const { userID } = res.locals;
      const access_token = await UserService.getAccessToken(userID);
      const result = await WeixinMaterialService.getItem({ access_token, media_id });
      res.status(200).json(result);
    } catch (error) {
      next(error);
    }
  })();
});

/**
 * 删除素材
 */
router.post('/:media_id/delete', (req, res, next) => {
  (async () => {
    try {
      const { media_id } = req.params;

      // 数据校验
      if (!media_id) {
        const error = new Error();
        error['errcode'] = 10001;
        error['errmsg'] = '缺少参数media_id';
        return next(error);
      }

      const { userID } = res.locals;

      const access_token = await UserService.getAccessToken(userID);
      const result = await WeixinMaterialService.deleteItem({ access_token, media_id });
      res.status(200).json(result);
      // 删除本地的同步素材库对应数据
      await MediaService.deleteMedia(media_id);
    } catch (error) {
      next(error);
    }
  })();
});
/**
 * 更新图文素材
 */
router.post('/:media_id/update', checkContent, (req, res, next) => {
  (async () => {
    try {
      const { media_id } = req.params;
      const { articles, index } = req.body;

      if (!articles) {
        const error = new Error();
        error['errcode'] = 10002;
        error['errmsg'] = '素材类型参数错误';
        return next(error);
      }

      const { userID } = res.locals;
      const access_token = await UserService.getAccessToken(userID);
      const result = await WeixinMaterialService.updateArticle({ access_token, media_id, index, articles });

      res.status(200).json(result);
    } catch (error) {
      next(error);
    }
  })();
});

export default router;
